import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError, of as ObservableOf } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { NzMessageService } from 'ng-zorro-antd/message';

@Injectable()
export class BaseInterceptor implements HttpInterceptor {
  // TODO: unsure for environment acquire
  private baseUrl = (window as any).environment.apiBaseUrl;
  private geoserverUrl = (window as any).environment.geoserverUrl;

  constructor(private router: Router, private message: NzMessageService) {}

  intercept(req, next: HttpHandler): Observable<any> {
    let url = req.url;
    if (!url.startsWith('https://') && !url.startsWith('http://')) {
      if (url.startsWith('/geoserver')) {
        url = `${this.geoserverUrl}${url}`;
      } else if (url.startsWith('assets')) {
        console.log('加载本地配置');
      } else {
        url = `${this.baseUrl}${url}`;
      }
    }
    const newReq = req.clone({ url });
    if (url.indexOf('login') === -1) {
      // login url may be different, need to be more specific
      const token = localStorage.getItem('token');
      const mid = localStorage.getItem('nxszyMid');
      if (token) {
        newReq.headers = newReq.headers.set('token', token);
      }
      if (mid) {
        newReq.headers = newReq.headers.set('mid', mid);
      }
    }
    // send cloned request with header to the next handler.
    return next.handle(newReq).pipe(
      mergeMap(response => {
        if (response instanceof HttpResponse) {
          return this.handleResponse(response);
        }
        return ObservableOf(response);
      }),
      catchError(error => {
        return this.handleResponse(error);
      })
    );
  }

  // private redirectTo(url: string): void {
  //     setTimeout(() => this.router.navigateByUrl(url));
  // }

  private handleResponse(
    response: HttpResponse<any> | HttpErrorResponse
  ): Observable<any> {
    if (response.status === 200) {
      // TODO: 预留200状态下的错误处理
      // TODO: 处理成功状态下的response body
      return ObservableOf(response || new HttpResponse());
    } else {
      return this.handleResponseError(response);
    }
  }

  private handleResponseError(
    response: HttpResponse<any> | HttpErrorResponse
  ): Observable<any> {
    switch (response.status) {
      case 401: // 未登录状态码
        localStorage.removeItem('token');
        localStorage.removeItem('userInfo');
        this.message.error('请重新登录');
        return throwError(response);
      case 403:
        this.message.error('无权限访问');
        return throwError(response);
      case 404:
        this.message.error('资源不存在');
        return throwError(response);
      default:
        if (response instanceof HttpErrorResponse) {
          return throwError(response);
        }
    }
    return ObservableOf(response);
  }
}
